
--[=[

@Angin ©版权所有
QQ 2440866962
Q群 992444856

全网高仿rlgg工具箱出自 @折纸

--]=]

user = {
	Author = 'Angin',
	data = {
		['admin'] = {
			qq = {
				2440866962,
				1851099569
			},
			qun = {
				473538067
			}
		},
		--使用教程
		['tutorial'] = 'https://lanzoux.com/igrKE0t7sssb',
		--配置路径
		cfg = gg['EXT_FILES_DIR']..'/',
	}
}


function main()
	:: label ::
	local tmp = {}
	table.insert(tmp, '联系客服')
	table.insert(tmp, '使用教程')
	table.insert(tmp, '注册账号')
	table.insert(tmp, '添加账号')
	if #GetObj.data.localdata.user[Url] >= 1 then
		table.insert(tmp, '删除账号')
	end
	table.insert(tmp, '变更网盘')
	table.insert(tmp, '找回密码')
	table.insert(tmp, '清除缓存')
	table.insert(tmp, '退出程序\n'..logo)
	local mc = #tmp
	for _, v in ipairs(GetObj.data.localdata.user[Url]) do
		table.insert(tmp, '\n'..v[3]..' · '..v[6]..'\n'..v[1]..'\nReg date: '..v[5])
	end
	if not site_notice then
		vsn, tips = '社区版', 'NULL'
	else
		vsn, tips = '捐助版', site_notice
	end
	if not string.match(tips, '%S') then
		tips = '站长比较有个性，什么都没写'
	end
	if #tips > 100 then
		tips = '公告过长, 无法显示...'
	end
	local Switch = gg.choice(tmp, nil, title..'\t·\t'..vsn..'\nURL: '..Url..'\n-\t注册状态:\t'..registerEnabled..'\n-\t登录验证码:\t'..loginCaptcha..'\n-\t注册验证码:\t'..regCaptcha..'\n-\t公告:\t'..tips..'\n'..logo)
	if Switch then
		if tmp[Switch] == '退出程序\n'..logo then
			os.exit()
		elseif tmp[Switch] == '变更网盘' then
			replaceUrl()
		elseif tmp[Switch] == '联系客服' then
			addrQQ()
		elseif tmp[Switch] == '使用教程' then
			gg.goURL(user.data.tutorial)
		elseif tmp[Switch] == '找回密码' then
			toResetPass()
			--gg.goURL(Url..'/forget')
		elseif tmp[Switch] == '注册账号' then
			reg()
		elseif tmp[Switch] == '清除缓存' then
			Cache()
		elseif tmp[Switch] == '添加账号' then
			addacc()
		elseif tmp[Switch] == '删除账号' then
			reacc()
		else
			login_init = GetObj.data.localdata.user[Url][Switch - mc]
			login_start()
		end
		goto label
	end
end

--添加账号
function addacc()
	zh, mm = nil, nil
	:: start ::
	local pr = gg.prompt({'账号', '密码'}, {zh or '', mm or ''}, {'text', 'text'})
	if pr then
		local log_in = login({pr[1], pr[2]})
		if not log_in then
			zh, mm = pr[1], pr[2]
			goto start
		end
		if not log_in then
			return
		end
		zh, mm = nil, nil
		for _, v in ipairs(GetObj.data.localdata.user[Url]) do
			if v[1] == pr[1] then
				gg.alert('账号列表已有此账号,无需重复添加')
				return
			end
		end
		table.insert(GetObj.data.localdata.user[Url], {
			pr[1],
			pr[2],
			log_in.json.data.nickname,
			log_in.cookie[1],
			iso8601(log_in.json.data.created_at),
			log_in.json.data.group.name,
			log_in.json.data.id
		})
		config.set(Obj_name, GetObj)
	end
end

--添加管理员
function addrQQ()
	local Qq = gg.choice(user.data.admin.qq, nil, '添加好友请说明来历!')
	if Qq then
		qq.join(user.data.admin.qq[Qq])
		gg.copyText(user.data.admin.qq[Qq])
		--gg.alert2('Angin', '添加好友请说明来历!')
	end
end

--群组
function addrQun()
	local qun = gg.choice(user.data.admin.qun, nil, '个人只需添加一个群组')
	if qun then
		qq.joinGroup(user.data.admin.qun[qun])
		gg.copyText(user.data.admin.qun[qun])
		gg.alert2('Angin', '请遵守群规!')
	end
end


Cache = function()
	if (gg.alert2(title, '即将清空本地数据并恢复初始网盘,是否继续?', '取消', '继续') == 2) then
		storages.remove('@rlgg-angin')
		GetObj, Url = toinit()
		local urlerr = http.get(Url..Api.config)
		Webinfo = json.decode(urlerr.content).data
		--登录验证码
		loginCaptcha = trueORfalse(Webinfo.loginCaptcha, {'开启', '关闭'})
		--注册验证码
		regCaptcha = trueORfalse(Webinfo.regCaptcha, {'开启', '关闭'})
		--账号注册
		registerEnabled = trueORfalse(Webinfo.registerEnabled, {'开放', '禁止'})
		--标题
		title = Webinfo.title
		--网站公告
		site_notice = Webinfo.site_notice
	end
end

--修改密码
ChangePass = function()
	local m1, m2
	local tmp = {'原密码', '新密码', '重复新密码'}
	:: start ::
	local cp = gg.prompt(tmp, {login_init[2], m1 or '', m2 or ''}, {'text', 'text', 'text'})
	if cp then
		m1, m2 = cp[2], cp[3]
		for i, v in ipairs(cp) do
			if not string.match(v, '%S') then
				gg.alert(tmp[i]..'不能为空')
				goto start
			end
		end
		if cp[2] ~= cp[3] then
			gg.alert2(title, '新密码与重复新密码不一致')
			goto start
		end
		local mp = modPass({cp[1], cp[2]})
		if mp.code == 40069 then
			gg.alert2(title, '原始密码错误,请检查原密码是否正确')
			goto start
		end
		if mp.code ~= 0 then
			m1, m2 = cp[2], cp[3]
			gg.alert2(title, mp.code..'\n'..http.get(Api.translat..mp.msg).content..'\n'..mp.msg)
			goto start
		end
		login_init[2] = cp[2]
		config.set(Obj_name, GetObj)
		GetObj, Url = toinit()
		gg.alert2(title, '修改成功\n新密码: '..m1)
		return
	end
end




--云容器
Cloud_Container_menu = function()

	:: start ::
	if not FOLDER then
		FOLDER = CFolder(GetObj.data.cloud.containers)
	end
	
	--获取存储策略
	Storage_Policy = FOLDER.data.policy.type

	local tbl, real = {}, table.length(FOLDER.data.objects)
	table.insert(tbl, '新增容器')
	if table.length(FOLDER.data.objects) > 0 then
		table.insert(tbl, '删除容器')
	end
	table.insert(tbl, '退出容器\n' .. logo)
	for _, v in pairs(FOLDER.data.objects) do
		if v.type == 'dir' then
			table.insert(tbl, '\n容器名称:\t' .. v.name .. '\n创建日期:\t' .. iso8601(v.create_date))
		end
	end
	
	local menu = gg.choice(tbl, nil, real .. '\n' .. logo)
	if menu then
		if tbl[menu] == '退出容器\n' .. logo then
			FOLDER = nil
			while_true(loginMain)
			return
		end
		goto start
	end
end



--获取目录
catalog_drive = function()
	:: start ::
	if not FOLDER then
		FOLDER = CFolder('/')
	end
	gg.alert(tostring(FOLDER))
	
end

Cloud_drive_menu = function()

end


--创建项目(云更新)
Cloud_Update_Create = function()
	local pr = gg.prompt({'项目名称'}, {''}, {'text'})
	if pr then
		if CFolder(GetObj.data.cloud.update .. '/' .. pr[1]) then
			gg.alert('创建成功')
			FOLDER = nil
		end
	end
end

--删除项目(云更新)
Cloud_Update_delete = function()
	local tbl, id = {}, {}
	for _, v in pairs(FOLDER.data.objects) do
		if v.type == 'dir' then
			table.insert(tbl, v.name)
			table.insert(id, v.id)
		end
	end
	local multi = gg.multiChoice(tbl, nil, '选择需删除的项目')
	if multi then
		for i in pairs(multi) do
			deleteDir(id[i])
		end
		FOLDER = nil
	end
end

--上传更新
upload_update = function(data)
	:: start ::
	local paths = login_init.path
	if not paths then
		login_init.path = {}
		config.set(Obj_name, GetObj)
		goto start
	end
	if not login_init.path.update then
		login_init.path.update = {}
		config.set(Obj_name, GetObj)
		goto start
	end
	
	local pr = gg.prompt({'选择更新文件'}, {paths.update[data.id] or gg.EXT_STORAGE}, {'file'})
	if pr then
		local toload, error = loadfile(pr[1])
		if not toload then
			gg.alert(error)
			goto start
		end
		
		local read = dump(file.read(pr[1]))
		local url = start_upload({
			url_path = GetObj.data.cloud.update .. '/' .. data.name,
			size = #read,
			name = 'Script.lua',
			id = FOLDER.data.policy.id,
			date = hmTime(),
			mime = getMIME(file.getName(pr[1])),
			content = read
		}, true)
		if url then
			:: start2 ::
			local FOLDER_Up = CFolder(GetObj.data.cloud.update .. '/' .. data.name)
			for _, v in pairs(FOLDER_Up.data.objects) do
				if v.type == 'file' then
					if v.name == 'Update.ini' then
						UpdateID = v.id
					end
				end
			end
			if not UpdateID then
				CreateFile(GetObj.data.cloud.update .. '/' .. data.name .. '/Update.ini')
				goto start2
			end
			local LOAD = [[
			update_data = {
				url = ']] .. url .. [[',
				date = ]] .. getAbsTime() .. [[,
				name = ']] .. data.name .. [[',
			}
			]]
			if upload_file(UpdateID, dump(LOAD)) then
				gg.alert('更新成功')
			end
		end
		paths.update[data.id] = pr[1]
		config.set(Obj_name, GetObj)
	end
end

--内置代码(云更新)
Cloud_Update_code = function(data)
	local FOLDER_Up = CFolder(GetObj.data.cloud.update .. '/' .. data.name)
	for _, v in pairs(FOLDER_Up.data.objects) do
		if v.type == 'file' then
			if v.name == 'Update.ini' then
				UpdateID = v.id
			end
		end
	end
	if not UpdateID then
		gg.alert('请先上传更新一个项目')
		return
	end
	local url = StraightChain({UpdateID})
	if url then
		pcall(load(http.get(url).content))
		local builtin = httpH(update_data.url)
		file.write(data.name .. '-内置代码.lua', '--[[\n' .. builtin .. '\n]]\n\n' .. 'loadYunLuaGroup(\'' .. builtin .. '\')')
		gg.copyText(builtin)
		gg.alert('已保存至同目录下的:\t' .. data.name .. '-内置代码.lua')
	end
end

--文件重命名
new_rename_dir = function(data)
	local pr = gg.prompt({'名称'}, {data.name}, {'text'})
	if pr then
		rename_dir(data.id, pr[1])
		FOLDER = nil
	end
end

--前置函数
front_fun = function(data)
	:: start ::
	local paths = login_init.path
	if not paths then
		login_init.path = {}
		config.set(Obj_name, GetObj)
		goto start
	end
	if not login_init.path['Front-facing'] then
		login_init.path['Front-facing'] = {}
		config.set(Obj_name, GetObj)
		goto start
	end

	local msg = [[功能介绍
执行项目前执行的函数 (rlgg可执行)
可以是公告,防御,防抓包...
]]
	local pr = gg.prompt({msg}, {paths['Front-facing'][data.id] or gg.EXT_STORAGE}, {'file'})
	if pr then
		local toload, error = loadfile(pr[1])
		if not toload then
			gg.alert(error)
			goto start
		end
		
		local FOLDER = CFolder(GetObj.data.cloud.update .. '/' .. data.name)
		for _, v in pairs(FOLDER.data.objects) do
			if v.type == 'file' then
				if v.name == 'Update.ini' then
					UpdateID = v.id
				end
			end
		end
		if not UpdateID then
			gg.alert('请先上传更新一个项目')
			return
		end
		pcall(load(fileContent(UpdateID)))
		print(update_data)
		if upload_file(UpdateID, [=[
		update_data = {
			url = ']=] .. update_data.url .. [=['
			date = ]=] .. update_data.date .. [=[
			name = ']=] .. update_data.name .. [=['
			front = [[]=] .. dump(file.read(pr[1])) .. [=[]]
		}
		]=]) then
			gg.alert('添加成功')
		end
		UpdateID = nil
		paths['Front-facing'][data.id] = pr[1]
		config.set(Obj_name, GetObj)
	end
end

Cloud_Update_menu2 = function(data)
	local tbl, info = {}, file_info(data.id, true)
	table.insert(tbl, '上传更新')
	table.insert(tbl, '内置代码')
	table.insert(tbl, '删除')
	table.insert(tbl, '重命名')
	--table.insert(tbl, '前置函数')
	local menu = gg.choice(tbl, nil, '项目名称:\t' .. data.name .. '\n占据容量:\t' .. getBytes(info.data.size) .. '\t\t(' .. info.data.size .. '\t字节)\n' .. logo)
	if menu then
		if tbl[menu] == '上传更新' then
			upload_update(data)
		elseif tbl[menu] == '内置代码' then
			Cloud_Update_code(data)
		elseif tbl[menu] == '前置函数' then
			front_fun(data)
		elseif tbl[menu] == '删除' then
			if random_code(4) then
				deleteDir(data.id)
				FOLDER = nil
			end
		elseif tbl[menu] == '重命名' then
			new_rename_dir(data)
		end
	end
end

--云更新
Cloud_Update_menu = function()
	:: start ::
	if not FOLDER then
		FOLDER = CFolder(GetObj.data.cloud.update)
	end
	
	--获取存储策略
	Storage_Policy = FOLDER.data.policy.type
	
	local tbl, real, tem = {}, table.length(FOLDER.data.objects), {}
	table.insert(tbl, '新建项目')
	if real > 0 then
		table.insert(tbl, '删除项目')
	end
	table.insert(tbl, '退出程序\n' .. logo)
	local tbls = #tbl
	for _, v in pairs(FOLDER.data.objects) do
		if v.type == 'dir' then
			table.insert(tbl, '项目名称:\t' .. v.name .. '\n更新日期:\t' .. iso8601(v.date))
			table.insert(tem, {
				name = v.name,
				id = v.id,
				size = getBytes(v.size),
				date = iso8601(v.date)
			})
		end
	end
	local Choice = gg.choice(tbl, nil, '项目数量:\t' .. real .. '\n' .. logo)
	if Choice then
		if tbl[Choice] == '退出程序\n' .. logo then
			FOLDER = nil
			while_true(loginMain)
			return
		elseif tbl[Choice] == '新建项目' then
			Cloud_Update_Create()
		elseif tbl[Choice] == '删除项目' then
			Cloud_Update_delete()
		else
			Cloud_Update_menu2(tem[Choice - tbls])
		end
		goto start
	end
end


--云文件上传
CloudURL_upload = function()
	local pr = gg.prompt({'选择文件'}, {GetObj.data.Curl or gg.EXT_STORAGE}, {'file'})
	if pr then
		local read = file.read(pr[1])
		local url = start_upload({
			url_path = GetObj.data.cloud.files,
			size = #read,
			name = file.getName(pr[1]),
			id = FOLDER.data.policy.id,
			date = hmTime(),
			mime = getMIME(file.getName(pr[1])),
			content = read
		})
		if url then
			if (gg.alert2('上传成功', url, '复制') == 1) then
				gg.copyText(url)
				gg.alert2('复制成功', '已复制到粘贴板\n' .. url)
			end
		end
		FOLDER = nil
		GetObj.data.Curl = pr[1]
		config.set(Obj_name, GetObj)
	end
end

--删除文件
CloudURL_delete = function()
	local tbl, id = {}, {}
	for _, v in pairs(FOLDER.data.objects) do
		if v.type == 'file' then
			table.insert(tbl, v.name)
			table.insert(id, v.id)
		end
	end
	local multi = gg.multiChoice(tbl, nil, '选择需删除的文件')
	if multi then
		for i in pairs(multi) do
			deleteFile(id[i])
		end
		FOLDER = nil
	end
end

--批量生成直链
batch_generate = function()
	local tbl, id = {}, {}
	for _, v in pairs(FOLDER.data.objects) do
		if v.type == 'file' then
			table.insert(tbl, v.name)
			table.insert(id, v.id)
		end
	end
	local multi = gg.multiChoice(tbl, nil, '选择需生成直链的文件')
	if multi then
		local batch = {}
		for i, v in pairs(multi) do
			table.insert(batch, id[i])
		end
		local char = ''
		for i, v in pairs(StraightChain(batch)) do
			char = char .. string.deUrl(v.url) .. '\n'
		end
		local  date = os.time()
		file.write('批量生成直链' .. date .. '.txt', char)
		gg.alert2('生成成功', char .. '直链已保存至同目录下的:\t批量生成直链' .. date .. '.txt')
	end
end

--文件重命名
new_rename_file = function(data)
	local pr = gg.prompt({'名称'}, {data.name}, {'text'})
	if pr then
		rename_file(data.id, pr[1])
		FOLDER = nil
	end
end

--编辑文件
edit_file = function(data)
	local path = file.getdirs(gg.EXT_STORAGE .. '/angin/')
	local url = StraightChain({data.id})
	local path = gg.EXT_STORAGE .. '/angin' .. string.deUrl(url:match('/[^/]+$'))
	local msg = '正在下载至本地，请稍后...' .. '\n' .. path
	local ok, err = luajava.download(url, path, msg)
	if not ok then
		gg.alert(err)
		return
	end
	local alert = gg.alert('已保存至目录:\t' .. path .. '\n打开文件并编辑, 编辑后点击悬浮窗上传保存, 此方式不会导致外链变更', '打开', '复制路径')
	if alert == 1 then
		file.open(path)
	elseif alert == 2 then
		gg.copyText(path)
		gg.alert('复制成功,打开文件编辑后点击悬浮窗上传更新\n' .. path)
	end
	
	gg['setVisible'](false)
	while true do
		if gg['isVisible'](true) then
			local alert = gg.alert('是否更新?更新不会导致原本的外链变更', '更新', '继续编辑', '取消编辑')
			if (alert == 1) then
				local content, error = file.read(path)
				if not content then
					gg.alert2('更新失败', error)
					break
				end
				if upload_file(data.id, file.read(path)) then
					gg.alert('更新成功')
					file.delete(path)
					FOLDER = nil
					break
				end
			elseif (alert == 3) then
				local content, error = file.read(path)
				if not content then
					gg.alert2('error', error)
					break
				end
				file.delete(path)
				break
			end
			gg['setVisible'](false)
		end
	end
end

CloudURL2 = function(data)
	:: start ::
	local tbl2 = {}
	table.insert(tbl2, '查看直链')
	table.insert(tbl2, '编辑')
	table.insert(tbl2, '删除')
	table.insert(tbl2, '重命名')
	local menu = gg.choice(tbl2, nil, data.name .. '\t·\t' .. data.size .. '\n' .. data.date .. '\n' .. logo)
	if menu then
		if tbl2[menu] == '查看直链' then
			local url = StraightChain({data.id})
			if url then
				if (gg.alert2('直链', url, '复制') == 1) then
					gg.copyText(url)
					gg.alert2('复制成功', '已复制到粘贴板\n' .. url)
				end
			end
		elseif tbl2[menu] == '重命名' then
			new_rename_file(data)
		elseif tbl2[menu] == '删除' then
			if random_code(4) then
				deleteFile(data.id)
				FOLDER = nil
			end
		elseif tbl2[menu] == '编辑' then
			edit_file(data)
		end
	end
end

--云外链
CloudURL = function()
	:: start ::
	if not FOLDER then
		FOLDER = CFolder(GetObj.data.cloud.files)
	end
	
	--获取存储策略
	Storage_Policy = FOLDER.data.policy.type
	
	local tbl, data = {}, {}
	table.insert(tbl, '上传文件')
	if FOLDER.data.objects[1] then
		table.insert(tbl, '批量直链')
	end
	if FOLDER.data.objects[0] then
		table.insert(tbl, '删除文件')
	end
	table.insert(tbl, '退出程序\n' .. logo)
	local tbls = #tbl
	for _, v in pairs(FOLDER.data.objects) do
		if v.type == 'file' then
			table.insert(tbl, '\n文件名称:\t' .. v.name .. '\t·\t' .. v.id .. '\n文件大小:\t' .. getBytes(v.size) .. '\n上传日期:\t' .. iso8601(v.date))
			table.insert(data, {
				name = v.name,
				id = v.id,
				size = getBytes(v.size),
				date = iso8601(v.date)
			})
		end
	end
	local menu = gg.choice(tbl, nil, '云外链\t·\t' .. #tbl - tbls .. '\n' .. logo)
	if menu then
		if tbl[menu] == '退出程序\n' .. logo then
			FOLDER = nil
			while_true(loginMain)
			return
		elseif tbl[menu] == '上传文件' then
			CloudURL_upload()
		elseif tbl[menu] == '删除文件' then
			CloudURL_delete()
		elseif tbl[menu] == '批量直链' then
			batch_generate()
		else
			CloudURL2(data[menu - tbls])
		end
		goto start
	end
end


--base64解码
debase64 = function(data)
	local b = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
	-- 补全 Base64 缺少的符号
	data = string.gsub(data, '[^'..b..'=]', '')
	data = string.gsub(data, '.', function(x)
		if x == '=' then return '' end
		local r,f='',(b:find(x) or 0)-1
		for i=6,1,-1 do r=r..(f%2^i-f%2^(i-1)>0 and '1' or '0') end
		return r;
	end)
	data = string.gsub(data, '%d%d%d?%d?%d?%d?%d?%d?', function(x)
		if (#x ~= 8) then return '' end
		local c=0
		for i=1,8 do c=c+(x:sub(i,i)=='1' and 2^(8-i) or 0) end
		return string.char(c)
	end)
	return data
end

dump = function(path)
	func = load(path)
	--编译文件
	code = string.dump(func, true)
	return code
end

--计算字节
getBytes = function(bytes)
	local bytes = bytes..'.0'
	if tonumber(bytes) < 1024 then
		return string.format('%.2f', bytes)..' B'
	elseif tonumber(bytes) >= 1073741824 then
		return string.format('%.2f', bytes/1024/1024/1024)..' GB'
	elseif tonumber(bytes) >= 1048576 then
		return string.format('%.2f', bytes/1024/1024)..' MB'
	else
		return string.format('%.2f', bytes/1024)..' KB'
	end
end


--获取mime类型
getMIME = function(file_name)
	local URLConnection = luajava.bindClass('java.net.URLConnection')
	local FileNameMap = luajava.bindClass('java.net.FileNameMap')
	local file_ext = string.match(file_name, '%.([^%.]+)$')
	if not file_ext then
		return nil
	end
	local map = URLConnection:getFileNameMap()
	if type(_ENV.android) ~= 'table' then
		mime_type = map.getContentTypeFor('file.' .. file_ext)
	else
		mime_type = map:getContentTypeFor('file.' .. file_ext)
	end
	return mime_type or ''
end

--获取毫秒时间戳
hmTime = function()
	local sec, usec = os.time(), 0
	if os.clock then
		usec = os.clock() * 1e6 % 1e6
	end
	local milliseconds = sec * 1000 + math.floor(usec / 1000)
	return milliseconds
end

--内置代码
httpH = function(data)
	local http_ = 'httpH'
	return http_..tostring(string.bin2hex(string.dump(load('pcall(load(http.get("'..data..'").content))'), true, true)))
end

--验证码Cookie
imageCode = function()
	local code = getCode()
	a, b = string.find(code[1], '"data:image/png;base64,(.-)","msg"')
	c = string.sub(code[1], a + 23, b - 7)
	file.write(user.data.cfg..'image', base64.decode('\''..c..'\''))
	return code[2], user.data.cfg..'image'
end

--ISO 8601 转时间戳
function iso8601(time)
	local content = string.gsub(time, "[%[=]", ""):gsub("%]", ":")
	local year, month, day, hour, min, sec = string.match(content, '(%d+)-(%d+)-(%d+)T(%d+):(%d+):(%d+)')
	local timestamp = os.time({
		year = tonumber(year),
		month = tonumber(month),
		day = tonumber(day),
		hour = tonumber(hour),
		min = tonumber(min),
		sec = tonumber(sec)
	})
	return os.date('%Y-%m-%d %H:%M:%S', timestamp)
end


login_start = function()
	local alert = gg.alert2(login_init[3], '当前账号\n'..login_init[1], '登录', '编辑昵称', '修改密码')
	if alert == 1 then
		Cookie = login_init[4]
		GetObj.data.localdata.login = login_init
	--	config.set(Obj_name, GetObj)
		aos()
		while_true(loginMain)
	elseif alert == 2 then
		new_name()
	elseif alert == 3 then
		ChangePass()
	end
end


--登录验证码
loginCode = function()

	local function getVerification(name)
		local editText = luajava.getIdView(name)
		if not isUserdata(editText) then
			gg.alert(string.format('%s-控件不存在', name))
			return
		end
		return editText:getText()
	end
	
	:: start ::
	
	local code_cookie = imageCode()
	
	local layout = {
		LinearLayout,
		padding = '10dp',
		{
			EditText,
				layout_width = 'start',
				layout_weight = 1,
				layout_marginEnd = '5dp', -- 右边距
				hint = '请输入验证码',
				text = '',
				textColor = '#66CBFA',
				id = luajava.newId('验证码'),
		},
		{
			ImageView, -- android.widget.ImageView
			layout_width = '60dp',
			layout_height = '30dp',
			src = user.data.cfg..'image'
		}
	}

	local alert = gg.newAlert(nil, msg)
	local view = luajava.loadlayout(layout)
	alert:setView(view)

	local Alert = gg.showAlert(alert, '确认', '取消', '刷新')
	if Alert == 1 then
		if tostring(getVerification('验证码')) == '' then
			gg.alert('未输入验证码')
			goto start
		end
		return tostring(getVerification('验证码')), code_cookie
	elseif Alert == 3 then
		goto start
	end
	return
end


--登录菜单
loginMain = function()

	if not perinfo then
		--账号信息更新
		perinfo = profile(login_init[7])
		login_init[6] = perinfo.data.user.group
		login_init[3] = perinfo.data.user.nick
		config.set(Obj_name, GetObj)
	end

	local tmp = {}
	table.insert(tmp, '打开网盘')
	table.insert(tmp, '免费内置')
	table.insert(tmp, '云更新\t·\t'..title)
	table.insert(tmp, '云容器\t·\t'..title)
	table.insert(tmp, '云外链\t·\t'..title)
	table.insert(tmp, '云网盘\t·\t'..title)
	table.insert(tmp, '加密工具')
	if site_notice then
		table.insert(tmp, '购买会员')
	end
	table.insert(tmp, '切换账号')
	table.insert(tmp, '退出程序')
	:: start ::
	local logincd = gg.choice(tmp, nil, login_init[3]..'\t·\t'..login_init[6]..'\n'..login_init[1]..'\n容量: '..used..' · '..free..'\n'..logo)
	if logincd then
		FOLDER = nil
		if tmp[logincd] == '切换账号' then
			local perinfo
			GetObj.data.localdata.login = nil
			Storage_Policy = nil
			config.set(Obj_name, GetObj)
			while_true(main)
			return
		elseif tmp[logincd] == '退出程序' then
			os.exit()
		elseif tmp[logincd] == '打开网盘' then
			gg.goURL(Url .. '/login?username=' .. login_init[1])
		elseif tmp[logincd] == '购买会员' then
			pay()
		elseif tmp[logincd] == '云外链\t·\t'..title then
			while_true(CloudURL)
		elseif tmp[logincd] == '云更新\t·\t'..title then
			while_true(Cloud_Update_menu)
		elseif tmp[logincd] == '云容器\t·\t'..title then
			while_true(Cloud_Container_menu)
		elseif tmp[logincd] == '云网盘\t·\t'..title then
			catalog_drive()
		end
		goto start
	end
end



--编辑名称
new_name = function()
	local n = gg.prompt({'名称'}, {login_init[3]}, {'text'})
	if n then
		local en = editName(n[1])
		if en.code ~= 0 then
			gg.alert2('error', en.code..'\n'..http.get(Api.translat..en.msg).content..'\n'..en.msg)
			return
		end
		login_init[3] = n[1]
		config.set(Obj_name, GetObj)
		GetObj, Url = toinit()
		gg.alert2(title, '修改成功')
	end
end

--添加账号
newac = function()
	
end


startsWith = function(tbl)
	for _, v in ipairs(tbl) do
		if string.startsWith(v[1], v[2]) then
			return true
		end
	end
end

urlLog = function()
	
end

replaceUrl = function()
	local help = [=[· 输入 "日志" 查看历史更新记录

· 输入 "历史" 查看历史网盘记录

· 非捐助版没有网站公告功能]=]
	:: start ::
	local pr = gg.prompt({'填入已搭建Cloudreve的域名\n·\tCloudreve官网\thttps://cloudreve.org\n·\t工具箱最初应用版本\t3.8.0\n·\t输入框输入 "详情" 查看帮助\n·\t---\t@Angin ©版权所有'}, {storageUrl or Url}, {'text'})
	if pr then
		if string.endsWith(pr[1], '/') then
			pr[1] = pr[1]:gsub('/$', '')
		end
		if not string.match(pr[1], '%S') then
			gg.alert2('哈哈', '...')
			goto start
		end
		storageUrl = pr[1]
		if storageUrl == '详情' then
			if (gg.alert2('详情', help, '确定', '取消', 'Cloudreve') == 3) then
				gg.goURL('https://cloudreve.org')
			end
			goto start
		elseif storageUrl == '历史' then
			local tmp = {}
			for i in pairs(GetObj.data.localdata.user) do
				if i == Url then
					i = '✔\t' .. i
				end
				table.insert(tmp, i)
			end
			:: start2 ::
			local old = gg.choice(tmp, nil, '选择历史网盘')
			if old then
			--[[
				local alert = gg.alert2(Url, '对该网盘进行操作', '选择', '删除', '编辑')
				if alert == 1 then
					if tmp[old] == '✔\t' .. Url then
						gg.alert2(Url, '已选择该网盘!')
						goto start2
					end
				elseif alert == 2 then
					table.remove(GetObj.data.localdata.user, tmp[old])
					print(GetObj.data.localdata.user)
				end
			]]
				if tmp[old] == '✔\t' .. Url then
					gg.alert2(Url, '已选择该网盘!')
					goto start2
				end
				storageUrl = tmp[old]
				
			else
				goto start
			end
		end
		if not startsWith({{storageUrl, 'http://'}, {storageUrl, 'https://'}}) then
			gg.alert2('url不合法', '检查协议是否正确\n\n"'..storageUrl..'"')
			goto start
		end
		if storageUrl == Url then
			gg.alert2('url变更提醒', '...')
			goto start
		end
		--检查域名是否可用
		local urlerr = http.get(storageUrl..Api.config)
		if type(json.decode(urlerr.content)) ~= 'table' then
			gg.alert2(storageUrl, '\n如果你看到这条弹窗说明你提供的网盘链接有问题\n\n·\t检查域名\t"'..storageUrl..'"\t是否正确\n\n·\t检查网盘是否可以被正常访问\n\n·\t检查是否已搭建Cloudreve网盘\n\n·\t检查ip是否已解析到域名\n\n·\t检查网盘版本是否\t>=\t3.8.0\n\n·\t检查防火墙5212端口是否开放\n\n·\t检查所搭建的网盘是否为官方版本(二开概率较低...)')
			goto start
		end
		
		Webinfo = json.decode(urlerr.content).data
		--登录验证码
		loginCaptcha = trueORfalse(Webinfo.loginCaptcha, {'开启', '关闭'})
		--注册验证码
		regCaptcha = trueORfalse(Webinfo.regCaptcha, {'开启', '关闭'})
		--账号注册
		registerEnabled = trueORfalse(Webinfo.registerEnabled, {'开放', '禁止'})
		--标题
		title = Webinfo.title
		--网站公告
		site_notice = Webinfo.site_notice
		
		GetObj.data.host.url[1] = storageUrl
		if not GetObj.data.localdata.user[storageUrl] then
			GetObj.data.localdata.user[storageUrl] = {}
		end
		config.set(Obj_name, GetObj)
		Url = GetObj.data.host.url[1]
		GetObj = config.get(Obj_name)
		--gg.alert2('url变更提醒', '原:\t' .. Url .. '\n\n现:\t' .. storageUrl)
	end
	storageUrl = nil
end

--随机验证码
security = function(a)
	local ck = {'1', '2', '3', '4', '5', '6', '7', '8', '9', '0'}
	local mark = ''
	for i = 1, a do
		uuid = math['random'](1, #ck)
		mark = mark .. ck[uuid]
	end
	return mark
end

--验证码
random_code = function(v)
	code = security(v)
	local pr = gg.prompt({'输入验证码 '..code}, {''}, {'text'})
	if pr then
		if pr[1] == code then
			return true
		else
			gg.alert('验证码错误!')
			return
		end
	end
end

--删除账号
function reacc()
	local tmp = {}
	for _, v in ipairs(GetObj.data.localdata.user[Url]) do
		table.insert(tmp, v[1])
	end
	local multiChoice = gg.multiChoice(tmp)
	if multiChoice then
		local useri = {}
		for i in pairs(multiChoice) do
			table.insert(useri, i)
		end
		for i = #useri, 1, -1 do
			table.remove(GetObj.data.localdata.user[Url], useri[i])
		end
		config.set(Obj_name, GetObj)
	end
end

--注册账号
reg = function()

	if registerEnabled == '禁止' then
		gg.htmlAlert(nil, '<h3>禁止注册</h3><p>该网盘禁止注册新用户,请联系网站管理员! ! !</p><a href="">参数设置 _>> 注册与登录 _>> 允许新用户注册</a>')
		return
	end

	Input_tbl = nil

	:: start ::
	if regCaptcha == '关闭' then
		code_cookie = ''
	else
		code_cookie = imageCode()
	end
	local Input = regui(user.data.cfg..'image', Input_tbl, {95, 30})
	if Input then
		if Input[1] == 'true' then
			Input_tbl = {
				Input[2].mail,
				Input[2].pass,
				Input[2]['repeat-pass'],
				'',
			}
			goto start
		elseif Input[1] == 'false' then
			return
		else
			if Input.pass ~= Input['repeat-pass'] then
				gg.alert2('error', '两次密码不一致!!!')
				Input_tbl = {
					Input.mail,
					Input.pass,
					Input['repeat-pass'],
					'',
				}
				goto start
			end
			local judge = registered(Input.mail, Input.pass, Input.code, code_cookie)
			if judge.code == 40026 then
				gg.alert2('error', '验证码错误!!!')
				Input_tbl = {
					Input.mail,
					Input.pass,
					Input['repeat-pass'],
					'',
				}
				goto start
			elseif judge.code == 40001 then
				gg.alert2('error', '检查邮箱格式是否正确')
				Input_tbl = {
					Input.mail,
					Input.pass,
					Input['repeat-pass'],
					'',
				}
				goto start
			elseif judge.code == 0 then
				gg.alert2('success', '注册成功!')
				local login = login({Input.mail, Input.pass})
				if not login then
					gg.alert2(title, '自动登录失败,请稍后手动添加账号')
					return
				end
				table.insert(GetObj.data.localdata.user[Url], {
					Input.mail,
					Input.pass,
					login.json.data.nickname,
					login.cookie[1],
					iso8601(login.json.data.created_at),
					login.json.data.group.name,
					login.json.data.id
				})
				config.set(Obj_name, GetObj)
			elseif judge.code == 203 or judge.code == 40033 then
				while true do
					if gg['isVisible'](true) then
						alert = gg.alert2('已发送激活邮件到您的电子邮箱', '邮件预计5分钟内到达,期间请勿重新注册或者退出,如果不存在则查看一下垃圾箱,如果10分钟后仍未收到,请重新注册', '已收到邮件,下一步', '点击我隐藏')
							if alert == 2 then
								gg['setVisible'](false)
							elseif alert == 1 then
								while true do
									if gg['isVisible'](true) then
										local prompt = gg.prompt({'请输入激活链接'}, {''}, {'tezt'})
										if prompt then
											http.get(prompt[1])
											return
										else
											gg['setVisible'](false)
										end
									end
								end
							end
						gg['setVisible'](false)
					end
				end
			else
				Input_tbl = {
					Input.mail,
					Input.pass,
					Input['repeat-pass'],
					'',
				}
				gg.alert2('error', judge.code..'\n'..http.get(Api.translat..judge.msg).content..'\n'..judge.msg)
				goto start
			end
		end
	end
end

--注册账号框
regui = function(url, cont, t)

	tem_pic = nil

	:: main ::
	if not cont then
		cont = {}
		for i = 1, 4 do
			table.insert(cont, '')
		end
	end

	InputResult=nil
	local lock = luajava.getBlock()
	local alert = luajava.newAlert()
	luajava.post(function()
		alert = alert:create()
	end)

	local function getVerification(name)
		local editText = luajava.getIdView(name)
		if not isUserdata(editText) then
			gg.alert(string.format('%s-控件不存在', name))
			return
		end
		return editText:getText()
	end

	local function exit()
		alert:dismiss()
		lock('end')
	end

	local function newGradientDrawableLayout(layout)
		local baseLayout = {
			GradientDrawable,
			cornerRadius = '15dp',
			color = '#00000000'
		}
		return table.copy(baseLayout, layout)
	end

	local function newButtonLayout(layout)
		local baseLayout = {
			Button,
			layout_width = 'match_parent',
			layout_margin = '5dp',
			background = newGradientDrawableLayout()
		}

		return table.copy(baseLayout, layout)
	end

	if regCaptcha == '关闭' then
		code_text = '未开启注册验证码无需输入'
		tem_pic = 'http://oss.angin.cn/logo/angin.png'
	else
		code_text = '请输入验证码'
	end

	view = luajava.loadlayout({
		LinearLayout,
		orientation = 'vertical',
		background = newGradientDrawableLayout({color = '#00000000'}), -- 主题颜色
		padding = {'5dp', '10dp', '5dp', '10dp'},
		{
			LinearLayout,
			layout_gravity = 'center',
			{
				ImageView,
				layout_width = '240dp',
				layout_height = '60dp',
				background = newGradientDrawableLayout({color = '#00000000'}),
				src = 'http://oss.angin.cn/logo/angin.png',
				id = luajava.newId('图片')
			},
		},
		
		{
			LinearLayout,
			layout_gravity = 'center',
			{
				TextView,
				layout_weight = 1,
				background = newGradientDrawableLayout({color = '#1f55ffff'}),
				text = 'Sign up Angin.',
			},
		},
		
		{
			LinearLayout,
			layout_gravity = 'start',
			{
				ImageView,
				layout_width = '30dp',
				layout_height = '30dp',
				layout_gravity = 'center',
				src = 'http://oss.angin.cn/logo/logo/邮箱4.png',
				id = luajava.newId('图片')
			},
			{
				EditText,
				layout_width = 'start',
				layout_weight = 1,
				layout_marginEnd = '5dp', -- 右边距
				hint = '电子邮箱',
				text = tostring(cont[1]),
				textColor = '#1E9F93',
				id = luajava.newId('电子邮箱'),
			},
		},
		{
			LinearLayout,
			layout_gravity = 'start',
			{
				ImageView,
				layout_width = '30dp',
				layout_height = '30dp',
				layout_gravity = 'center',
				src = 'http://oss.angin.cn/logo/logo/输入密码_密码.png',
				id = luajava.newId('图片')
			},
			{
				EditText,
				layout_width = 'start',
				layout_weight = 1,
				layout_marginEnd = '5dp', -- 右边距
				hint = '密码',
				text = tostring(cont[2]),
				textColor = '#66CBFA',
				id = luajava.newId('密码'),
			},
		},
		{
			LinearLayout,
			layout_gravity = 'start',
			{
				ImageView,
				layout_width = '30dp',
				layout_height = '30dp',
				layout_gravity = 'center',
				src = 'http://oss.angin.cn/logo/logo/再次输入密码2.png',
				id = luajava.newId('图片')
			},
			{
				EditText,
				layout_width = 'start',
				layout_weight = 1,
				layout_marginEnd = '5dp', -- 右边距
				hint = '重复密码',
				text = tostring(cont[3]),
				textColor = '#66CBFA',
				id = luajava.newId('重复密码'),
			},
		},
		
		{
			LinearLayout,
			layout_gravity = 'start',
			{
				ImageView,
				layout_width = '30dp',
				layout_height = '30dp',
				layout_gravity = 'center',
				src = 'http://oss.angin.cn/logo/logo/验证码.png',
				id = luajava.newId('图片')
			},
			{
				EditText,
				layout_width = 'start',
				layout_weight = 1,
				layout_marginEnd = '5dp', -- 右边距
				hint = code_text,
				text = tostring(cont[4]),
				textColor = '#fff000',
				id = luajava.newId('验证码'),
			},
			{
				ImageView,
				layout_width = t[1]..'dp',
				layout_height = t[2]..'dp',
				layout_gravity = 'center',
				src = tem_pic or url,
				id = luajava.newId('图片')
			},
		},
		
		newButtonLayout({
			LinearLayout,
			--orientation = 'horizontal',
			layout_width = 'wrap_content',
			color = '#00000000',
			layout_gravity = 'end', -- 设置布局位置为靠右
			{
				Button,
				color = '#00000000',
				text = '刷新',
				background = newGradientDrawableLayout({color = '#11111111'}),
				onClick = function()
					InputResult = {
						'true', 
						{
							['mail'] = tostring(getVerification('电子邮箱')),
							['pass'] = tostring(getVerification('密码')),
							['repeat-pass'] = tostring(getVerification('重复密码')),
							['code'] = tostring(getVerification('验证码'))
						}
					}
					alert:dismiss()
				end
			},
			{ --空白按钮 凑数...
				Button,
				color = '#00000000',
				text = stamp2 or 'Angin',
				background = newGradientDrawableLayout({color = '#00000000'}),
				onClick = function()
					ck = {'不要戳啦ヽ(`Д´)ﾉ', '嘤嘤嘤～', '好啦好啦'}
					uuid = math['random'](1, #ck)
					gg.toast('不要戳啦ヽ(`Д´)ﾉ')
					stamp = true
					stamp2 = ck[uuid]
					alert:dismiss()
				end
			},
			{
				Button,
				color = '#00000000',
				text = '取消',
				background = newGradientDrawableLayout({color = '#11111111'}),
				onClick = function()
					InputResult = {'false'}
					alert:dismiss()
				end
			},
			{
				Button,
				color = '#00000000',
				text = '确定',
				background = newGradientDrawableLayout({color = '#11111111'}),
				layout_marginStart = '10dp', -- 左边距
				onClick = function()
					local function func()
						alert:dismiss()
						InputResult = {
							['mail'] = tostring(getVerification('电子邮箱')),
							['pass'] = tostring(getVerification('密码')),
							['repeat-pass'] = tostring(getVerification('重复密码')),
							['code'] = tostring(getVerification('验证码'))
						}
					end
					luajava.startThread(func)
				end
			},
		}),
		
	})
	alert:setView(view)
	
	alert:setOnDismissListener(luajava.createProxy('android.content.DialogInterface$OnDismissListener', {
		onDismiss = function()
			exit()
		end
	}))
	
	luajava.showAlert(alert)
	
	lock('join')
	
	if stamp then
		stamp = nil
		goto main
	end
	
	stamp2 = nil
	
	if InputResult then
		return InputResult
	end
end

toinit = function()

	:: start ::
	
	--创建存储对象
	config = storages.create('@rlgg-angin')
	
	Obj_name = 'rlgg-cfg'
	
	logo = '----------------------'
	
	--返回存储对象
	GetObj = config.get(Obj_name)
	
	--初始化数据库表格
	if not GetObj then
		config.set(Obj_name, {
			['data'] = {}
		})
		goto start
	end
	
	--self-protocol
	if not GetObj.data.host then
		GetObj.data.host = {}
		--GetObj.data.host['self-protocol'] = 'https://'
		
		GetObj.data.host.url = {
			'https://cloud.angin.cn'
		}
		GetObj.data.host.log = {}
		config.set(Obj_name, GetObj)
		goto start
	end
	
	--初始化网盘配置
	if not GetObj.data['cloud'] then
		GetObj.data['cloud'] = {}
		local Cloud = '/Angin&Toolbox'
		GetObj.data['cloud'] = {
			['update'] = Cloud..'/update',
			['containers'] = Cloud..'/containers',
			['files'] = Cloud..'/files'
		}
		config.set(Obj_name, GetObj)
		goto start
	end
	
	--初始化本地数据
	if not GetObj.data.localdata then
		GetObj.data.localdata = {
			user = {
				[tostring(GetObj.data.host.url[1])] = {
					path = {}
				}
			},
			login = nil,
		}
		config.set(Obj_name, GetObj)
		goto start
	end
	
	Url = GetObj.data.host.url[1]
	
	return GetObj, Url
end

toResetPass = function()
	local pr = gg.prompt({'注册邮箱'}, {''}, {'text'})
	if pr then
		local tips = json.decode(toReset({pr[1], nil}).content)
		if tips.code == 0 then
			gg.alert2(title, '✅\t密码重置邮件已发送，请注意查收')
		else
			gg.alert2(tips.code, http.get(Api.translat..tips.msg).content..'\n'..tips.msg)
		end
	end
end

trueORfalse = function(t, tbl)
	if t == 'true' then
		return tbl[1]
	end
	return tbl[2]
end

function while_true(fun, ...)
	while true do
		if gg['isVisible'](true) then
			fun(...)
			gg['setVisible'](false)
		end
	end
end


--购买商品
pay = function()

	product_init = product()
	
	local tmp = {}
	id = {}
	for _, v in pairs(product_init.data.groups) do
		Int = ''
		for _, v2 in pairs(v.des) do
			Int = Int..v2..'\n'
		end
		table.insert(id, v.id)
		table.insert(tmp, v.name..'\n'..(v.price / 100)..'元\n'..Int)
	end
	
	choice = gg.choice(tmp, 0, '标题标题标题test')
	
	if choice then
		local corr = order(id[choice])
		if corr.code ~= 0 then
			gg.alert2('error', corr.code..'\n'..http.get(Api.translat..corr.msg).content..'\n'..corr.msg)
			return
		end
		gg.goURL(corr.data.qr_code)
		
		gg['setVisible'](false)
		while true do
			if gg['isVisible'](true) then
				if (gg.alert('是否已付款？', '已付款', '取消') == 1) then
					--[[
					inspect = order(id[choice], true)
					print(inspect)
					if inspect.code == 404 then
						gg.alert2('error', '未收到付款记录,请重新下单', '关闭')
						return
					elseif inspect.code ~= 0 then
						gg.alert2('error', inspect.code..'\n'..http.get(Api.translat..inspect.msg).content..'\n'..inspect.msg)
					end
					if inspect.data == 1 then
						gg.alert2('支付完成', '您所购买的商品已到账。', '关闭')
						return
					end
					]]
					gg.alert2('支付提醒', '如果商品未到账请检查是否付款。', '关闭')
					return
				end
				gg['setVisible'](false)
			end
		end
		
	end

end


--Url = get_cfg.data.host.url[1]
Api = {

	--翻译接口
	translat = 'https://api.tangdouz.com/fy.php?nr=',

	--登录接口
	session = '/api/v3/user/session',
	--注册接口
	user = '/api/v3/user',
	--网站配置
	config = '/api/v3/site/config',
	--找回密码
	reset = '/api/v3/user/reset',
	--验证码
	captcha = '/api/v3/site/captcha',
	--存储容量
	storage = '/api/v3/user/storage',
	--编辑昵称
	nick = '/api/v3/user/setting/nick',
	--修改密码
	password = '/api/v3/user/setting/password',
	--个人主页
	profile = '/api/v3/user/profile',
	--创建文件
	create = '/api/v3/file/create',
	--获取目录
	directory = '/api/v3/directory',
	--获取直链
	source = '/api/v3/file/source',
	--商品列表
	product = '/api/v3/vas/product',
	--发起购买请求
	order = '/api/v3/vas/order',
	--上传
	upload = '/api/v3/file/upload',
	--编辑文件
	update = '/api/v3/file/update',
	--删除文件
	object = '/api/v3/object',
	--修改名称
	rename = '/api/v3/object/rename',
	--文件&文件夹信息
	property = '/api/v3/object/property',
	--文件内容
	content = '/api/v3/file/content',
	
	--上传策略
	--OneDrive
	onedrive = '/api/v3/callback/onedrive/finish',
	 
}


--登录
function login(t)
	Input_code = ''
	if loginCaptcha == '关闭' then
		code_cookie = ''
	else
		:: start ::
		Input_code, code_cookie = loginCode()
		if not Input_code then
			return
		end
	end
	local re = http.post(Url..Api.session, nil, '{"captchaCode":"'..Input_code..'","userName":"'..t[1]..'","Password":"'..t[2]..'"}')
	local json_re = json.decode(re.content)
	if json_re.code ~= 0 then
		gg.alert2(json_re.code, http.get(Api.translat..json_re.msg).content..'\n'..json_re.msg)
		return
	end
	if type(json_re) ~= 'table' then
		return nil, re
	end
	return {
		['json'] = json_re,
		['cookie'] = re.headers['Set-Cookie']
	}
end

--找回密码
toReset = function(tbl)
	if not tbl[2] then
		tbl[2] = ''
	end
	return http.post(Url..Api.reset, nil, '{"userName":"'..tbl[1]..'","captchaCode":"'..tbl[2]..'"}')
end

--获取验证码
getCode = function()
	local ret = http.get(Url..Api.captcha)
	return {
		ret.content,
		ret.headers['Set-Cookie'][1]
	}
end

--注册接口
registered = function(name, pass, captcha, Cookie)
	if not captcha then
		captcha = ''
	end
	return json.decode(http.post(Url..Api.user, {
		['Cookie'] = Cookie
	}, '{"userName":"'..name..'","Password":"'..pass..'","captchaCode":"'..captcha..'"}').content)
end

--存储容量
aos = function()
	local tbl = json.decode(http.get(Url..Api.storage, {
		['Cookie'] = Cookie
	}).content)
	if tbl.code ~= 0 then
		gg.alert2('error', tbl.code..'\n'..http.get(Api.translat..tbl.msg).content..'\n'..tbl.msg)
		while_true(main)
		return
	end
	
	--已使用
	used = getBytes(tbl.data.used)
	--剩余
	free = getBytes(tbl.data.free)
	--总共
	total = getBytes(tbl.data.total)
--[[
	if tbl.data.free <= (1024 ^ 2) then
		gg.htmlAlert(nil, '<h3>容量预警</h3><p>您所在的用户组 "'..login_init[6]..'" 剩余容量为 '..free..', 可能导致工具无法被正常使用</p><a href="">管理员请前往后台设置: 用户组 _>> '..login_init[6]..' _>> 初始容量 增加容量即可解决</a>')
	end
]]
	return tbl
end

--编辑昵称
editName = function(name)
	return json.decode(http.patch(Url..Api.nick, {
		['Cookie'] = Cookie
	}, '{"nick":"'..name..'"}').content)
end

--修改密码
modPass = function(tbl)
	return json.decode(http.patch(Url..Api.password, {
		['Cookie'] = Cookie
	}, '{"old":"'..tbl[1]..'","new":"'..tbl[2]..'"}').content)
end

--个人主页
profile = function(id)
	return json.decode(http.get(Url..Api.profile..'/'..id..'?page=1&type=default', {
		['Cookie'] = Cookie
	}).content)
end

--创建文件
CreateFile = function(path)
	return http.post(Url..Api.create, {
		['Cookie'] = Cookie
	}, '{"path":"'..path..'"}')
end

--获取目录
GetFOLDER = function(path)
	return json.decode(http.get(Url..Api.directory..path, {
		['Cookie'] = Cookie
	}).content)
end

--创建并返回文件夹
CFolder = function(path)
	:: check ::
	local FOLDER = GetFOLDER(path)
	if FOLDER.msg == 'Path not exist' then
		local info = json.decode(http.put(Url..Api.directory, {
			['Cookie'] = Cookie
		}, '{"path":"'..path..'"}').content)
		if info.code ~= 0 then
			gg.alert2('error', info.code..'\n'..http.get(Api.translat..info.msg).content..'\n'..info.msg)
			return
		end
		goto check
	end
	return FOLDER
end

--获取直链
StraightChain = function(arr)
	local strArr = {}
	for _, v in ipairs(arr) do
		table.insert(strArr, tostring(v))
	end
	local str = table.concat(strArr, '","')
	str = '"' .. str .. '"'
	local url = json.decode(http.post(Url..Api.source, {
		['Cookie'] = Cookie
	}, '{"items":['..str..']}')['content']).data
	if not url then
		local lock = GetFOLDER('/')
		gg.htmlAlert(nil, '<h3>无法获取直链</h3><p>您所在的用户组 "'..login_init[6]..'" 的存储策略无法直接获取直链,此设置会导致全部功能失效请联系网盘管理员开启</p><a href="">管理员请前往后台设置:<br></br><br></br>1. 存储策略 _>> '..lock.data.policy.name..' _>> 初始容量 _>> 向导模式编辑 _>> 直链设置 设置为允许</a><br></br><a href=""><br></br>2. 用户组 _>> '..perinfo.data.user.group..' _>> 批量生成外链数量限制 改为10</a>')
		return nil
	end
	if url[0].url == '' then
		return nil
	end
	if table.length(url) > 1 then
		return url
	end
	return string.deUrl(url[0].url)
end

--内容
fileContent = function(id)
	return http.get(Url..Api.content .. '/' .. id, {
		['Cookie'] = Cookie
	}).content
end

--商品列表
product = function()
	return json.decode(http.get(Url..Api.product, {
		['Cookie'] = Cookie
	}).content)
end

--发起购买
order = function(id, TRUE)
	if TRUE then
		mode = http.get
		path, body = '/'..id, nil
		
	else
		mode = http.post
		body, path = '{"action":"group","method":"custom","id":'..id..',"num":1}', ''
	end
	return json.decode(mode(Url..Api.order..path, {
		['Accept'] = 'application/json, text/plain, */*',
		['Cookie'] = Cookie
	}, body).content)
end

--删除文件
deleteFile = function(id)
	local info = json.decode(http.delete(Url..Api.object, {
		['Cookie'] = Cookie
	}, [[{
  "items": [
	"]]..id..[["
  ],
  "dirs": [],
  "force": false,
  "unlink": false
}]]).content)
	if info.code ~= 0 then
		gg.alert2('error', info.code..'\n'..http.get(Api.translat..info.msg).content..'\n'..info.msg)
		return
	end
	return info
end

--删除文件夹
deleteDir = function(id)
	local info = json.decode(http.delete(Url..Api.object, {
		['Cookie'] = Cookie
	}, [[{
  "items": [],
  "dirs": [
	"]]..id..[["
  ],
  "force": false,
  "unlink": false
}]]).content)
	if info.code ~= 0 then
		gg.alert2('error', info.code..'\n'..http.get(Api.translat..info.msg).content..'\n'..info.msg)
		return
	end
	return info
end

--文件重命名
rename_file = function(id, name)
	local info = json.decode(http.post(Url..Api.rename, {
		['Cookie'] = Cookie
	}, [[{
  "action": "rename",
  "src": {
    "dirs": [],
    "items": [
      "]] .. id .. [["
    ]
  },
  "new_name": "]] .. name .. [["
}]]).content)
	if info.code ~= 0 then
		gg.alert2('error', info.code..'\n'..http.get(Api.translat..info.msg).content..'\n'..info.msg)
		return
	end
	return info
end

--文件重命名
rename_dir = function(id, name)
	local info = json.decode(http.post(Url..Api.rename, {
		['Cookie'] = Cookie
	}, [[{
  "action": "rename",
  "src": {
    "items": [],
    "dirs": [
      "]] .. id .. [["
    ]
  },
  "new_name": "]] .. name .. [["
}]]).content)
	if info.code ~= 0 then
		gg.alert2('error', info.code..'\n'..http.get(Api.translat..info.msg).content..'\n'..info.msg)
		return
	end
	return info
end

--文件&文件夹信息
file_info = function(id, TYPE)
	local info = json.decode(http.get(Url..Api.property .. '/' .. id .. '?trace_root=false&is_folder=' .. tostring(TYPE), {
		['Cookie'] = Cookie
	}).content)
	if info.code ~= 0 then
		gg.alert2('error', info.code..'\n'..http.get(Api.translat..info.msg).content..'\n'..info.msg)
		return
	end
	return info
end

--清空上传会话
emptySession = function()
	local info = json.decode(http.delete(Url..Api.upload, {
		['Cookie'] = Cookie
	}).content)
	if info.code ~= 0 then
		gg.alert2('error', info.code..'\n'..http.get(Api.translat..info.msg).content..'\n'..info.msg)
		return
	end
	return info
end

--编辑文件
upload_file = function(id, ct)
	local info = json.decode(http.put(Url..Api.update .. '/' .. id, {
		['Cookie'] = Cookie
	}, ct).content)
	if info.code ~= 0 then
		gg.alert2('error', info.code..'\n'..http.get(Api.translat..info.msg).content..'\n'..info.msg)
		return
	end
	return info
end

--上传
upload = function(tbl, cover)
	:: start ::
	local info = json.decode(http.put(Url..Api.upload, {
		['Cookie'] = Cookie
	}, [[{
  "path": "]]..tbl.url_path..[[",
  "size": ]]..tbl.size..[[,
  "name": "]]..tbl.name..[[",
  "policy_id": "]]..tbl.id..[[",
  "last_modified": ]]..tbl.date..[[,
  "mime_type": "]]..tbl.mime..[["
}]]).content)
	--清空会话
	if info.code == 40054 then
		emptySession()
		goto start
	end
	--容量预警
	if info.code == 40051 then
		gg.htmlAlert(nil, '<h3>容量不足</h3><p>您所在的用户组 "'..login_init[6]..'" 剩余容量为 '..free..' 而本次上传需消耗容量 ' .. getBytes(tbl.size) .. ', 容量不足无法上传, 请联系网盘管理员</p><a href="">管理员请前往后台设置: 用户组 _>> '..login_init[6]..' _>> 初始容量 增加容量即可解决</a>')
		return
	end
	--是否覆盖？
	if cover then
		if info.code == 40004 then
			local FOLDER = GetFOLDER(tbl.url_path)
			for i, v in pairs(FOLDER.data.objects) do
				if v.type == 'file' then
					if v.name == 'Script.lua' then
						deleteFile(v.id)
					end
				end
			end
			goto start
		end
	end
	if info.code ~= 0 then
		gg.alert2('error', info.code..'\n'..http.get(Api.translat..info.msg).content..'\n'..info.msg)
		return
	end
	return info
end

--本地策略
local_strategy = function(tbl, cover)
	local ID = upload(tbl, cover)
	if not ID then
		return
	end
	local info = json.decode(http.post(Url..Api.upload .. '/' .. ID.data.sessionID .. '/0', {
		['Cookie'] = Cookie
	}, tostring(tbl.content)).content)
	if info.code ~= 0 then
		gg.alert2('error', info.code..'\n'..http.get(Api.translat..info.msg).content..'\n'..info.msg)
		return
	end
	--返回直链
	local FOLDER = GetFOLDER(tbl.url_path)
	for i, v in pairs(FOLDER.data.objects) do
		if v.type == 'file' then
			if v.name == tbl.name then
				return StraightChain({v.id})
			end
		end
	end
end

start_upload = function(tbl, cover)
	if Storage_Policy == 'local' then
		return local_strategy(tbl, cover)
	elseif Storage_Policy == 'onedrive' then
		return OneDrive(tbl, cover)
		--[[
	elseif Storage_Policy == 'oss' then
		return alyoss(tbl, cover)
		]]
	elseif Storage_Policy == 'qiniu' then
		return Qi_niu(tbl, cover)
	elseif Storage_Policy == 'upyun' then
		return up_oss(tbl, cover)
	else
		gg.alert2('未知的策略', Storage_Policy)
		return
	end
end

--alyoss
alyoss_upload = function(ID, tbl)
	local info = json.decode(http.put(ID.data.uploadURLs[0] .. '/1', {
		['Authorization'] = 'UpToken ' .. ID.data.credential,
	}, tbl.content).content)
	if info.error then
		gg.alert2('error', http.get(Api.translat..info.error).content..'\n'..info.error)
		return
	end
	return json.decode(http.post(ID.data.uploadURLs[0], {
		['Authorization'] = 'UpToken ' .. ID.data.credential,
	}, [[{
	"parts": [
		{
			"etag": "]] .. info.etag .. [[",
			"partNumber": 1
		}
	]
}]]).content)
end

alyoss = function(tbl, cover)
	local ID = upload(tbl, cover)
	if not ID then
		return
	end
	
	alyoss_upload(ID, tbl)
	
	--返回直链
	local FOLDER = GetFOLDER(tbl.url_path)
	for i, v in pairs(FOLDER.data.objects) do
		if v.type == 'file' then
			if v.name == tbl.name then
				return StraightChain({v.id})
			end
		end
	end
end


--OneDrive
OneDrive_upload = function(ID, tbl)
	local info = json.decode(http.put(ID.data.uploadURLs[0], {
		['content-range'] = 'bytes 0-' .. tbl.size - 1 .. '/' .. tbl.size
	}, tbl.content).content)
	if info.error then
		gg.alert2('error', http.get(Api.translat..info.error.code).content..'\n'..info.error.code..'\n'..http.get(Api.translat..info.error.message).content..'\n'..info.error.message)
		return
	end
	return json.decode(http.post(Url .. Api.onedrive .. '/' .. ID.data.sessionID, {
		['Cookie'] = Cookie
	}, '{}').content)
end

OneDrive = function(tbl, cover)
	local ID = upload(tbl, cover)
	if not ID then
		return
	end
	
	OneDrive_upload(ID, tbl)
	
	--返回直链
	local FOLDER = GetFOLDER(tbl.url_path)
	for i, v in pairs(FOLDER.data.objects) do
		if v.type == 'file' then
			if v.name == tbl.name then
				return StraightChain({v.id})
			end
		end
	end
end

--Qi_niu
Qi_niu_upload = function(ID, tbl)
	local info = json.decode(http.put(ID.data.uploadURLs[0] .. '/1', {
		['Authorization'] = 'UpToken ' .. ID.data.credential,
	}, tbl.content).content)
	if info.error then
		gg.alert2('error', http.get(Api.translat..info.error).content..'\n'..info.error)
		return
	end
	return json.decode(http.post(ID.data.uploadURLs[0], {
		['Authorization'] = 'UpToken ' .. ID.data.credential,
	}, [[{
	"parts": [
		{
			"etag": "]] .. info.etag .. [[",
			"partNumber": 1
		}
	]
}]]).content)
end

Qi_niu = function(tbl, cover)
	local ID = upload(tbl, cover)
	if not ID then
		return
	end
	
	Qi_niu_upload(ID, tbl)
	
	--返回直链
	local FOLDER = GetFOLDER(tbl.url_path)
	for i, v in pairs(FOLDER.data.objects) do
		if v.type == 'file' then
			if v.name == tbl.name then
				return StraightChain({v.id})
			end
		end
	end
end

--up_oss
up_oss_upload = function(ID, tbl)
	local Request_Body = '------WebKitFormBoundaryQ4AGNi0OU1wNsKu1\nContent-Disposition: form-data; name="policy"\n\n' .. ID.data.policy .. '\n------WebKitFormBoundaryQ4AGNi0OU1wNsKu1\nContent-Disposition: form-data; name="authorization"\n\n' .. ID.data.credential .. '\n------WebKitFormBoundaryQ4AGNi0OU1wNsKu1\nContent-Disposition: form-data; name="file"; filename="' .. tbl.name .. '"\nContent-Type: application/octet-stream\n\n' .. tbl.content .. '\n------WebKitFormBoundaryQ4AGNi0OU1wNsKu1--\n'
	
	local info = json.decode(http.post(ID.data.uploadURLs[0], {
		['Accept'] = 'application/json, text/plain, */*',
		['Content-Type'] = 'multipart/form-data; boundary=----WebKitFormBoundaryQ4AGNi0OU1wNsKu1'
	}, Request_Body).content)
	if info.error then
		gg.alert2('error', http.get(Api.translat..info.error).content..'\n'..info.error)
		return
	end
	return print(info)
end

up_oss = function(tbl, cover)
	local ID = upload(tbl, cover)
	if not ID then
		return
	end
	
	up_oss_upload(ID, tbl)
	
	--返回直链
	local FOLDER = GetFOLDER(tbl.url_path)
	for i, v in pairs(FOLDER.data.objects) do
		if v.type == 'file' then
			if v.name == tbl.name then
				return StraightChain({v.id})
			end
		end
	end
end




GetObj, Url = toinit()
--检查域名是否可用
local urlerr = http.get(Url..Api.config)
if type(json.decode(urlerr.content)) ~= 'table' then
	gg.alert2('网盘地址异常!', urlerr)
	replaceUrl()
	os.exit()
end

Webinfo = json.decode(urlerr.content).data
--登录验证码
loginCaptcha = trueORfalse(Webinfo.loginCaptcha, {'开启', '关闭'})
--注册验证码
regCaptcha = trueORfalse(Webinfo.regCaptcha, {'开启', '关闭'})
--账号注册
registerEnabled = trueORfalse(Webinfo.registerEnabled, {'开放', '禁止'})
--标题
title = Webinfo.title
--网站公告
site_notice = Webinfo.site_notice

login_init = GetObj.data.localdata.login
if login_init then
	Cookie = login_init[4]
	aos()
	while_true(loginMain)
end
while_true(main)
